package game.module.sss.procesor;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import game.common.PlayingRoleMsgProcessor;
import game.common.PrimitiveTypeConstants;
import game.entity.PlayingRole;
import game.module.sss.SssConstants;
import game.module.sss.bean.SssEnSortCardType;
import game.module.sss.bean.SssRound;
import game.module.sss.bean.TagAnalyseData;
import game.module.sss.logic.SssAlgorithm;
import game.module.sss.logic.SssDataManager;
import game.module.sss.logic.SssLogic;
import game.session.SessionManager;
import lion.common.MsgCodeAnn;
import lion.netty4.message.MyRequestMessage;
import lion.netty4.message.RequestMessageRaw;
import lion.netty4.message.RequestProtoMessage;
import lua.LuaMessageLogin.S2ErrorCode;
import lua.LuaMessageSss.C2SSssPeiPai;
import lua.LuaMessageSss.PushSssPeiPaiFinish;
import lua.LuaMessageSss.S2CSssPeiPai;

@MsgCodeAnn(msgcode = C2SSssPeiPai.id, accessLimit = 500)
public class SssPeiPaiProcessor extends PlayingRoleMsgProcessor {

	private static Logger logger = LoggerFactory.getLogger(SssPeiPaiProcessor.class);

	@Override
	public void process(PlayingRole playingRole, RequestMessageRaw request) throws Exception {
		C2SSssPeiPai reqMsg = C2SSssPeiPai.parse(request);
		byte[] player_show_pai = reqMsg.pai;
		boolean use_special = reqMsg.use_special;
		int playerId = playingRole.getId();
		logger.info("sss pei pai,playerId={},player_show_pais={},use_special={}", playerId, player_show_pai,
				use_special);
		// 房间是否存在
		final SssRound ddzRound = SssDataManager.getInstance().getNnRoom(playerId);
		if (ddzRound == null) {
			S2ErrorCode retMsg = new S2ErrorCode(201);
			playingRole.writeAndFlush(retMsg.build(playingRole.alloc()));
			return;
		}
		// 是否已经存在
		Map<Integer, byte[]> peiPaiFinishPlayers = ddzRound.getPeiPaiFinish();
		if (peiPaiFinishPlayers != null && peiPaiFinishPlayers.containsKey(playerId)) {
			S2ErrorCode retMsg = new S2ErrorCode(402);
			playingRole.writeAndFlush(retMsg.build(playingRole.alloc()));
			return;
		}
		// 牌数量够不够
		int myIndex = ddzRound.getPlayerIds().indexOf(playerId);
		byte[] myCards = ddzRound.getCards().get(myIndex);
		if (myCards == null || player_show_pai.length != SssConstants.HAND_CARD_COUNT) {
			S2ErrorCode retMsg = new S2ErrorCode(403);
			playingRole.writeAndFlush(retMsg.build(playingRole.alloc()));
			return;
		}
		// 去重
		Set<Byte> myCardsPass = new HashSet<>();
		for (int i = 0; i < player_show_pai.length; i++) {
			myCardsPass.add(player_show_pai[i]);
		}
		if (myCardsPass.size() < SssConstants.HAND_CARD_COUNT) {
			S2ErrorCode retMsg = new S2ErrorCode(404);
			playingRole.writeAndFlush(retMsg.build(playingRole.alloc()));
			return;
		}
		// 牌能否对的上
		for (Byte aCard : player_show_pai) {
			if (ArrayUtils.indexOf(myCards, aCard) == -1) {
				S2ErrorCode retMsg = new S2ErrorCode(405);
				playingRole.writeAndFlush(retMsg.build(playingRole.alloc()));
				return;
			}
		}
		// 是否为倒水
		boolean bDragon = isDaoShui(ddzRound, player_show_pai, myIndex,use_special);
		if (bDragon) {
			S2ErrorCode retMsg = new S2ErrorCode(401);
			playingRole.writeAndFlush(retMsg.build(playingRole.alloc()));
			return;
		}
		// 保存牌的信息
		ShowCard(ddzRound, player_show_pai, myIndex, use_special);
		// do
		if (peiPaiFinishPlayers == null) {
			peiPaiFinishPlayers = new HashMap<>();
			ddzRound.setPeiPaiFinish(peiPaiFinishPlayers);
		}
		peiPaiFinishPlayers.put(playerId, player_show_pai);
		// ret
		S2CSssPeiPai respMsg = new S2CSssPeiPai(PrimitiveTypeConstants.SHORT_ZERO);
		playingRole.writeAndFlush(respMsg.build(playingRole.alloc()));
		// 推送
		PushSssPeiPaiFinish pushSssPeiPaiFinish = new PushSssPeiPaiFinish((byte) myIndex);
		List<Integer> playerIds = ddzRound.getPlayerIds();
		for (Integer aPlayerId : playerIds) {
			PlayingRole pr = SessionManager.getInstance().getPlayer(aPlayerId);
			if (pr != null && pr.isChannelActive()) {
				pr.writeAndFlush(pushSssPeiPaiFinish.build(pr.alloc()));
			}
		}
		// 配牌是否完成
		if (peiPaiFinishPlayers.size() >= playerIds.size()) {
			SssLogic.getInstance().claculateResult(ddzRound);
			// 游戏结束清理数据
			if (ddzRound.getCurrentRound() >= ddzRound.getRoundCount()) {
				SssLogic.getInstance().allRoundOver(ddzRound);//全局结束
			}
		}
	}

	private boolean isDaoShui(SssRound ddzRound, byte[] player_show_pai, int myIndex, boolean use_special) {
		boolean bDragon = false;
		byte j = (byte) myIndex;
		SssAlgorithm m_GameLogic = ddzRound.getSssAlgorithm();
		List<byte[]> m_bUserCardData = ddzRound.getCards();
		byte cardType = m_GameLogic.GetCardType(m_bUserCardData.get(j), SssConstants.HAND_CARD_COUNT,
				m_GameLogic.btCardSpecialData);
		if (cardType == SssConstants.CT_INVALID || (cardType != SssConstants.CT_INVALID && !use_special)) {
			byte[] frontRow = Arrays.copyOfRange(player_show_pai, 0, 3);
			byte[] middleRow = Arrays.copyOfRange(player_show_pai, 3, 8);
			byte[] endRow = Arrays.copyOfRange(player_show_pai, 8, 13);
			if ((true == m_GameLogic.CompareCard(frontRow, middleRow, (byte) 3, (byte) 5, false,ddzRound.getSunzi_a()))
					&& (true == m_GameLogic.CompareCard(middleRow, endRow, (byte) 5, (byte) 5, false,ddzRound.getSunzi_a())))
				bDragon = false;
			else
				bDragon = true;
		}
		return bDragon;
	}

	private void ShowCard(SssRound ddzRound, byte[] player_show_pai, int myIndex, boolean use_special) {
		byte j = (byte) myIndex;
		byte[] m_bSpecialCardData = new byte[SssConstants.HAND_CARD_COUNT];// 特殊牌的数据
		SssAlgorithm m_GameLogic = ddzRound.getSssAlgorithm();
		List<byte[]> m_bUserCardData = ddzRound.getCards();
		byte[][][] m_bSegmentCard = ddzRound.getM_bSegmentCard();
		boolean[] m_bSpecialTypeTable = ddzRound.m_bSpecialTypeTable;
		if (m_GameLogic.GetCardType(m_bUserCardData.get(j), SssConstants.HAND_CARD_COUNT,
				m_GameLogic.btCardSpecialData) != SssConstants.CT_INVALID && use_special) {
			m_GameLogic.SortCardList(m_bUserCardData.get(j), SssConstants.HAND_CARD_COUNT, SssEnSortCardType.enDescend);

			byte m_bHandCardCount = SssConstants.HAND_CARD_COUNT;
			byte[] btSpecialCard = new byte[13];
			TagAnalyseData AnalyseData = new TagAnalyseData();
			m_GameLogic.AnalyseCard(m_bUserCardData.get(j), m_bHandCardCount, AnalyseData);
			if (m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
					btSpecialCard) == SssConstants.CT_THIRTEEN_FLUSH
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_THIRTEEN
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_TWELVE_KING
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_THREE_STRAIGHTFLUSH
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_THREE_BOMB
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_ALL_BIG
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_ALL_SMALL
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_SAME_COLOR
					|| m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
							btSpecialCard) == SssConstants.CT_FOUR_THREESAME) {
				// CopyMemory(m_bSpecialCardData,m_bUserCardData.get(j),sizeof(m_bSpecialCardData));
				System.arraycopy(m_bUserCardData.get(j), 0, m_bSpecialCardData, 0, m_bSpecialCardData.length);
			} else if (m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
					btSpecialCard) == SssConstants.CT_THREE_FLUSH) {
				// CopyMemory(m_bSpecialCardData,btSpecialCard,sizeof(btSpecialCard));
				System.arraycopy(btSpecialCard, 0, m_bSpecialCardData, 0, btSpecialCard.length);
			} else if (m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
					btSpecialCard) == SssConstants.CT_THREE_STRAIGHT) {
				// CopyMemory(m_bSpecialCardData,btSpecialCard,sizeof(btSpecialCard));
				System.arraycopy(btSpecialCard, 0, m_bSpecialCardData, 0, btSpecialCard.length);
			} else if (m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
					btSpecialCard) == SssConstants.CT_FIVEPAIR_THREE) {
				byte[] SaveData = new byte[5];
				SaveData[0] = m_bUserCardData.get(j)[AnalyseData.bThreeFirst[0]];
				SaveData[1] = m_bUserCardData.get(j)[AnalyseData.bThreeFirst[0] + 1];
				SaveData[2] = m_bUserCardData.get(j)[AnalyseData.bThreeFirst[0] + 2];
				m_GameLogic.RemoveCard(SaveData, (byte) 3, m_bUserCardData.get(j), m_bHandCardCount);
				m_bHandCardCount -= 3;
				m_GameLogic.SortCardList(m_bUserCardData.get(j), m_bHandCardCount,
						SssEnSortCardType.enDescend);
				for (int i = 0; i < m_bHandCardCount; i++) {
					m_bSpecialCardData[i] = m_bUserCardData.get(j)[i];
				}
				m_bUserCardData.get(j)[10] = m_bSpecialCardData[10] = SaveData[0];
				m_bUserCardData.get(j)[11] = m_bSpecialCardData[11] = SaveData[1];
				m_bUserCardData.get(j)[12] = m_bSpecialCardData[12] = SaveData[2];
			} else if (m_GameLogic.GetCardType(m_bUserCardData.get(j), m_bHandCardCount,
					btSpecialCard) == SssConstants.CT_SIXPAIR) {
				byte[] SaveData = new byte[5];
				SaveData[0] = m_bUserCardData.get(j)[AnalyseData.bOneFirst[0]];
				m_GameLogic.RemoveCard(SaveData, (byte) 1, m_bUserCardData.get(j), m_bHandCardCount);
				m_bHandCardCount -= 1;
				m_GameLogic.SortCardList(m_bUserCardData.get(j), m_bHandCardCount, SssEnSortCardType.enDescend);
				for (int i = 0; i < m_bHandCardCount; i++) {
					m_bSpecialCardData[i] = m_bUserCardData.get(j)[i];
				}
				m_bUserCardData.get(j)[12] = m_bSpecialCardData[12] = SaveData[0];
			}

			for (int i = 0; i < 3; i++) {
				m_bSegmentCard[j][0][i] = m_bSpecialCardData[10 + i];
			}

			for (int i = 0; i < 5; i++) {
				m_bSegmentCard[j][1][i] = m_bSpecialCardData[5 + i];
			}

			for (int i = 0; i < 5; i++) {
				m_bSegmentCard[j][2][i] = m_bSpecialCardData[i];
			}
			m_bSpecialTypeTable[j] = true;
			m_GameLogic.SortCardList(m_bSegmentCard[j][0], (byte) 3, SssEnSortCardType.enDescend);
			m_GameLogic.SortCardList(m_bSegmentCard[j][1], (byte) 5, SssEnSortCardType.enDescend);
			m_GameLogic.SortCardList(m_bSegmentCard[j][2], (byte) 5, SssEnSortCardType.enDescend);
		} else {
			// 内容设置
			System.arraycopy(player_show_pai, 0, m_bSegmentCard[j][0], 0, 3);
			System.arraycopy(player_show_pai, 3, m_bSegmentCard[j][1], 0, 5);
			System.arraycopy(player_show_pai, 8, m_bSegmentCard[j][2], 0, 5);
			m_GameLogic.SortCardList(m_bUserCardData.get(j), SssConstants.HAND_CARD_COUNT, SssEnSortCardType.enDescend);
			m_bSpecialTypeTable[j] = false;
			m_GameLogic.SortCardList(m_bSegmentCard[j][0], (byte) 3, SssEnSortCardType.enDescend);
			m_GameLogic.SortCardList(m_bSegmentCard[j][1], (byte) 5, SssEnSortCardType.enDescend);
			m_GameLogic.SortCardList(m_bSegmentCard[j][2], (byte) 5, SssEnSortCardType.enDescend);
		}
	}

	@Override
	public void processProto(PlayingRole playingRole, RequestProtoMessage request) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void processWebsocket(PlayingRole playingRole, MyRequestMessage request) throws Exception {
		// TODO Auto-generated method stub

	}

	public static void main(String[] args) {
		SssAlgorithm m_GameLogic = new SssAlgorithm();
		byte[] cardlist = new byte[] { 0x1D, 0x3C, 0x3B, 0x0A, 0x28, 0x18, 0x37, 0x26, 0x35, 0x34, 0x14, 0x33, 0x22 };
		byte m_bHandCardCount = SssConstants.HAND_CARD_COUNT;
		// byte[] btSpecialCard = new byte[13];
		byte ret = m_GameLogic.GetCardType(cardlist, m_bHandCardCount, m_GameLogic.btCardSpecialData);
		System.out.println(ret);
	}

}
